/**
 * Copyright (c) 2016-2020 https://github.com/zhaohuatai
 *
 * contact z_huatai@qq.com
 *  
 */
package org.zfes.snowy.auth.biz.service.impl;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zfes.snowy.auth.biz.dao.AuthUserPermissionMapper;
import org.zfes.snowy.auth.biz.model.AuthUserPermission;
import org.zfes.snowy.auth.biz.service.IAuthUserPermissionService;
import org.zfes.snowy.auth.shiro.event.AuthCacheClearType;
import org.zfes.snowy.auth.shiro.event.AuthChangeEvent;
import org.zfes.snowy.base.dao.params.ParamMap;
import org.zfes.snowy.core.data.DataSet;
import org.zfes.snowy.core.idcenter.IDGenerator;
import org.zfes.snowy.core.util.ZAlert;
import org.zfes.snowy.core.util.ZObjectUtil;
import org.zfes.snowy.core.util.ZStrUtil;

@Service
@Lazy(true)
public class AuthUserPermissionServiceImpl  implements IAuthUserPermissionService{
	
	@Autowired
	private AuthUserPermissionMapper authUserPermissionMapper;
	@Autowired
	private  ApplicationEventPublisher publisher;
//----------------------------------------------------------------------------------------------------	
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public List<String> loadPermCodesInUserPermByUserId(Long userId,String appkey,Boolean enabled) {
		if(userId==null||ZStrUtil.hasNoText(appkey)){
			return Collections.emptyList();
		}
		return authUserPermissionMapper.selectPermCodesByUserId(userId,appkey, enabled);
	}
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public List<Long> loadPermIdsInUserPermByUserId(Long userId,String appkey, Boolean enabled){
		if(userId==null||ZStrUtil.hasNoText(appkey)){
			return Collections.emptyList();
		}
		return authUserPermissionMapper.selectPermIdsByUserId(userId, appkey, enabled);
	}
	
	@Transactional(rollbackFor=Exception.class,readOnly=false)	
	@Override
	public void addPermsToUserPerm(List<Long> permissionIds, Long userId) {
		if(userId==null||ZObjectUtil.isEmpty(permissionIds)){
			ZAlert.Error("请选择数据");
		}
		permissionIds=permissionIds.stream().distinct().collect(Collectors.toList());
		
		removePermsFromUserPerm(permissionIds,userId);
		
		List<AuthUserPermission> userPermissionList = 
				permissionIds.stream()
				.map(permId->new AuthUserPermission(IDGenerator.genLongId(),permId, userId))
				.collect(Collectors.toList());
		
		authUserPermissionMapper.batchInsertUserPermission(userPermissionList);
		this.publisher.publishEvent(new AuthChangeEvent(SecurityUtils.getSubject(),AuthCacheClearType.cachedAuthorizationInfoBySubject));
	}
	@Transactional(rollbackFor=Exception.class,readOnly=false)	
	@Override
	public void removePermsFromUserPerm(List<Long> permissionIds, Long userId) {
		if(userId==null||ZObjectUtil.isEmpty(permissionIds)){
			ZAlert.Error("请选择数据");
		}
		permissionIds=permissionIds.stream().distinct().collect(Collectors.toList());
		authUserPermissionMapper.deletePermFromUserPermission(permissionIds, userId);
		this.publisher.publishEvent(new AuthChangeEvent(SecurityUtils.getSubject(),AuthCacheClearType.cachedAuthorizationInfoBySubject));
	}
//----------------------------------------------------------------------------------------------------
	
	@Transactional(rollbackFor=Exception.class,readOnly=true)	
	@Override
	public DataSet loadPermDataSetForUserAssign(Boolean isInUser ,Map<String, Object> params ) {
		ParamMap pm=ParamMap.filterParam(params);
		Optional<String> appKey=pm.getStr("appKey");
		Optional<Long> userId=pm.getLong("userId");
		
		if(!userId.isPresent()||!appKey.isPresent()){
			return DataSet.emptyDS();
		}
		pm.getStr("name").ifPresent(v->pm.updateParam( "name", "%"+v+"%"));
		pm.getStr("permCode").ifPresent(v->pm.updateParam( "permCode", "%"+v+"%"));
		pm.addParam("userId", userId.get());
		if(isInUser){
			return DataSet.newDS(authUserPermissionMapper.selectPermsInUserCount(pm), authUserPermissionMapper.selectPermsInUser(pm));
		} else{
			return DataSet.newDS(authUserPermissionMapper.selectPermsNotInUserCount(pm), authUserPermissionMapper.selectPermsNotInUser(pm));
		}
	}
}
